package com.liuche.homechat.common.websocket;

import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.liuche.homechat.common.common.utils.NettyUtil;
import com.liuche.homechat.common.websocket.domaiin.dto.WSAuthorize;
import com.liuche.homechat.common.websocket.domaiin.enums.WSReqTypeEnum;
import com.liuche.homechat.common.websocket.domaiin.vo.req.WSBaseReq;
import com.liuche.homechat.common.websocket.service.CustomWebSocketService;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;


@Slf4j
@Sharable
public class NettyWebSocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    private CustomWebSocketService customWebSocketService;

    /**
     * 处理创建连接的请求
     *
     * @param ctx
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        customWebSocketService = SpringUtil.getBean(CustomWebSocketService.class);
        customWebSocketService.connectActive(ctx.channel());
    }


    // 读取客户端发送的请求报文，根据传来的type值来判断用什么方法来进行处理
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
        String text = msg.text();
        System.out.println("收到前端发来的消息：" + text);
        // 得到前端传来的Json字符串再进行转换
        WSBaseReq wsBaseReq = JSONUtil.toBean(text, WSBaseReq.class);
        switch (WSReqTypeEnum.of(wsBaseReq.getType())) {
            case AUTHORIZE:
                customWebSocketService.handShakeAuthorize(ctx.channel(), WSAuthorize
                        .builder()
                        .token(wsBaseReq.getData())
                        .build());
                break;
            case HEARTBEAT:
                break;
            case LOGIN:
                log.info("登陆请求处理");
                customWebSocketService.loginAuthorize(ctx.channel());
        }
    }

    /**
     * 处理30秒之间前端没有发送心跳的方法，后期可以用于处理用户下线
     *
     * @param ctx
     * @param evt
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        Channel channel = ctx.channel();
        if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
            // 握手完成
            String token = NettyUtil.getAttr(channel, NettyUtil.TOKEN);
            if (StringUtils.isNotBlank(token)) {
                customWebSocketService.handShakeAuthorize(channel, WSAuthorize.builder()
                        .token(token)
                        .build());
            }

        } else if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                System.out.println("读空闲");
                channel.writeAndFlush(new TextWebSocketFrame("你很久没找我玩了，去你吗的"));
                customWebSocketService.unConnect(ctx);
            }
        }

        super.userEventTriggered(ctx, evt);
    }
}
